//
//  DownloadManager.m
//  MHO
//
//  Created by papo on 4/5/14.
//  Copyright (c) 2014 maihoang. All rights reserved.
//

#import "DownloadManager.h"
#import "Lib.h"
#import "SettingManager.h"
#import <AudioToolbox/AudioToolbox.h>


#define kDownloadFolder @"Downloads"


@interface NSURL(Custom)

@end

@implementation NSURL(Custom)

- (BOOL)isEquivalent:(NSURL *)aURL {

    if ([self isEqual:aURL]) return YES;
    if ([[self scheme] caseInsensitiveCompare:[aURL scheme]] != NSOrderedSame) return NO;
    if ([[self host] caseInsensitiveCompare:[aURL host]] != NSOrderedSame) return NO;

    // NSURL path is smart about trimming trailing slashes
    // note case-sensitivty here
    if ([[self path] compare:[aURL path]] != NSOrderedSame) return NO;

    // at this point, we've established that the urls are equivalent according to the rfc
    // insofar as scheme, host, and paths match

    // according to rfc2616, port's can weakly match if one is missing and the
    // other is default for the scheme, but for now, let's insist on an explicit match
    if ([[self port] compare:[aURL port]] != NSOrderedSame) return NO;

    if ([[self query] compare:[aURL query]] != NSOrderedSame) return NO;

    // for things like user/pw, fragment, etc., seems sensible to be
    // permissive about these.  (plus, I'm tired :-))
    return YES;
}

@end

@implementation DownloadManager


+ (DownloadManager*)sharedManager {
    static DownloadManager* m_staticDownloadMn = nil;
    static dispatch_once_t once;
    
    dispatch_once(&once, ^{
        if (m_staticDownloadMn == nil) {
            m_staticDownloadMn = [[self alloc] init];
            
            // init for TCB download manager
            [[TCBlobDownloadManager sharedInstance] setMaxConcurrentDownloads:2];
        }
    });

    return m_staticDownloadMn;
}

- (id) init {
    self = [super init];
    if (self) {
        self.listDownload = [[NSMutableArray alloc] init];
    }
    return self;
}

//+ (BOOL)startDownloadFileFromUrl:(NSURL *)url {
//    return [[self sharedManager] startDownloadFileFromUrl:url];
//}
//
//- (BOOL)startDownloadFileFromUrlString:(NSString *)url {
//    return [self startDownloadFileFromUrl:[NSURL URLWithString:url]];
//}
//
//- (BOOL)startDownloadFileFromUrl:(NSURL *)url {
//    return [self startDownloadFileFromUrl:url inDirectory:kDownloadFolder];
//}
//
//- (BOOL)startDownloadFileFromUrl:(NSURL *)url inDirectory:(NSString *)path {
//    if ([self fileUrlExist:url]) {
//        NSLog(@"File url request sent!");
//        return NO;
//    }
//    TCBlobDownloader* download = [[TCBlobDownloadManager sharedInstance] startDownloadWithURL:url customPath:path delegate:self];
//    if (download && ![self.listDownload containsObject:download]) {
//        [self.listDownload addObject:download];
//        return YES;
//    }
//    else {
//        NSLog(@"Download Manager::: download error!");
//        return NO;
//    }
//}

+ (TCBlobDownloader*)startDownload:(Application *)app {
    return [[self sharedManager ]startDownload:app];
}

- (TCBlobDownloader*)startDownload:(Application *)app {
    NSURL* url = [NSURL URLWithString:app.file];
//    for (TCBlobDownloader* downloader in _listDownload) {
//        if ([downloader.app.appId integerValue] == [app.appId integerValue]) {
//            return NO;
//        }
//    }
    TCBlobDownloader* downloader = [[TCBlobDownloadManager sharedInstance] startDownloadWithURL:url customPath:nil delegate:self];
    if (downloader && ![self.listDownload containsObject:downloader]) {
        [downloader setApp:app];
        [self.listDownload addObject:downloader];
        [self saveDownload:downloader finish:NO];
        return downloader;
    }
    
    return nil;
}

- (NSString*)getDocumentsPath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
    return basePath;
}

- (void)cancelDownloadAtIndex:(int)index {
    TCBlobDownloader* download = [self downloadAtIndex:index];
    if (download && ![download isFinished] && [download isCancelled] && [download isExecuting]) {
        [download cancelDownloadAndRemoveFile:YES];
    }
}

- (void )pauseDownloadAtIndex:(int)index {
    TCBlobDownloader* download = [self downloadAtIndex:index];
    if (download && ![download isFinished] && [download isCancelled] && [download isExecuting]) {
        [download cancelDownloadAndRemoveFile:NO];
    }
}

- (void)resumeDownloadAtIndex:(int)index {
    TCBlobDownloader* download = [self downloadAtIndex:index];
    if (download) {
        [download start];
    }
}

- (NSInteger)speedRateAtIndex:(int)index {
    TCBlobDownloader* download = [self downloadAtIndex:index];
    if (download) {
        return [download speedRate];
    }
    return 0;
}

- (NSInteger)remainTimeAtIndex:(int)index {
    TCBlobDownloader* download = [self downloadAtIndex:index];
    if (download) {
        return [download remainingTime];
    }
    return 0;
}


- (TCBlobDownloader*)downloadAtIndex:(int)index {
    if (index < 0 || index >= self.listDownload.count) {
        NSLog(@"Download Manager::: cancel download error! Index out of list array!");
        return nil;
    }
    return self.listDownload[index];
}

#pragma mark - TCB Download Manager Delegate
- (void)download:(TCBlobDownloader *)blobDownload didReceiveFirstResponse:(NSURLResponse *)response {

}

- (void)download:(TCBlobDownloader *)blobDownload
  didReceiveData:(uint64_t)receivedLength
         onTotal:(uint64_t)totalLength {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
    if ([[SettingManager shared] settingAtIndex:3]) {
        [[UIApplication sharedApplication] setIdleTimerDisabled:YES];
    }
}


- (void)download:(TCBlobDownloader *)blobDownload
didStopWithError:(NSError *)error {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    NSLog(@"DownloadManager:: download error: %@!", error.description);
    [[UIApplication sharedApplication] setIdleTimerDisabled:NO];
    
    [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationDownloadFailed object:blobDownload];
}


- (void)download:(TCBlobDownloader *)blobDownload
didFinishWithSucces:(BOOL)downloadFinished
          atPath:(NSString *)pathToFile {
    [self.listDownload removeObject:blobDownload];
    [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationDownloadSuccess object:blobDownload];
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    NSLog(@"DownloadManager:: download success file %@!", pathToFile);
    
    if (pathToFile) {
        [self saveDownload:blobDownload finish:downloadFinished || blobDownload.isFinished];
    }
    if (downloadFinished || blobDownload.isFinished) {
        NSLog(@"DownloadManager:: download success file %@!", pathToFile);
        if ([[SettingManager shared] settingAtIndex:5] ) {
            // playsoud
            NSString *path = [[NSBundle bundleWithIdentifier:@"com.apple.UIKit"] pathForResource:@"Tock" ofType:@"aiff"];
            SystemSoundID soundID;
            AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path], &soundID);
            AudioServicesPlaySystemSound(soundID);
            AudioServicesDisposeSystemSoundID(soundID);
        }
        
        if ([[SettingManager shared] settingAtIndex:2]) {
            [Lib installApp:blobDownload];
        }
        
        
        [[UIApplication sharedApplication] setIdleTimerDisabled:NO];
    }
}


- (NSArray*)getAllDownloadFile {
    NSString* folder = [[TCBlobDownloadManager sharedInstance] defaultDownloadPath];
    return [[NSFileManager defaultManager] contentsOfDirectoryAtPath:folder error:nil];
}

- (BOOL)fileUrlStringExist:(NSString*)url {
    return [self fileUrlExist:[NSURL URLWithString:url]];
}

- (BOOL)fileUrlExist:(NSURL*)url {
    for (TCBlobDownloader* download in self.listDownload) {
        if ([download.downloadURL isEquivalent:url]) {
            return YES;
        }
    }
    return NO;
}

- (void)saveDownload:(TCBlobDownloader*)downloader finish:(BOOL)finish {
    NSString* folder = [Lib getDocumentPath];
    NSString* file = [folder stringByAppendingPathComponent:@"download.plist"];
    NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithContentsOfFile:file];
    if (!dict) {
        dict = [NSMutableDictionary dictionary];
    }
    
    Application* app = downloader.app;
    NSMutableDictionary* appDict = [dict objectForKey:app.appName];
    if (!appDict) {
        appDict = [NSMutableDictionary dictionary];
    }
    
    [appDict setObject:app.appName forKey:@"appName"];
    [appDict setObject:app.imagePath forKey:@"icon"];
    [appDict setObject:app.file forKey:@"file"];
    [appDict setObject:app.plist forKey:@"plist"];
    [appDict setObject:[NSNumber numberWithBool:finish]  forKey:@"finish"];
    [appDict setObject:[NSNumber numberWithUnsignedLongLong:downloader.totalDataLength] forKey:@"totalsize"];
    [appDict setObject:[NSNumber numberWithUnsignedLongLong:downloader.receivedDataLength] forKey:@"receive"];
    
    if (downloader.fileName) {
        [appDict setObject:downloader.fileName forKey:@"path"];
    }
    else {
        [appDict setObject:[app.file lastPathComponent] forKey:@"path"];
    }
    
    // save
    [dict setObject:appDict forKey:app.appName];
    [dict writeToFile:file atomically:YES];
}

- (void)removeDownload:(TCBlobDownloader *)downloader {
    
        if (downloader) {
            Application* app = downloader.app;
            if (app) {
                [self removeAppFromList:app];
            }
            [downloader cancelDownloadAndRemoveFile:YES];
            [self.listDownload removeObject:downloader];
        }
}

- (void)removeAppFromList:(Application*)app {
    NSString* folder = [Lib getDocumentPath];
    NSString* file = [folder stringByAppendingPathComponent:@"download.plist"];
    NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithContentsOfFile:file];
    
    if (dict && [dict isKindOfClass:[NSMutableDictionary class]]) {
        if (app) {
            NSString* appName = app.appName;
            if (appName) {
                [dict removeObjectForKey:appName];
                [dict writeToFile:file atomically:YES];
            }
            
            NSString* filePath = [self getAppPath:app];
            if (filePath) {
                [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
            }
        }
    }else{
        NSLog(@"removeAppFromList - dict is not exist or not class NSMutableDictionary");
    }
    [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationRemoveDownload object:nil];
}

- (NSString*)getAppPath:(Application *)app {
    NSString* folder = [[TCBlobDownloadManager sharedInstance] defaultDownloadPath];
    NSString* file = [app.file lastPathComponent];
    file = [folder stringByAppendingPathComponent:file];
    NSLog(@"getAppPath -- find file path: %@", file);
    
    return file;
}

- (NSDictionary*)dictForDownload:(TCBlobDownloader *)downloader {
    NSString* folder = [Lib getDocumentPath];
    NSString* file = [folder stringByAppendingPathComponent:@"download.plist"];
    NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithContentsOfFile:file];
    if (!dict || downloader || downloader.app || downloader.app.appName) {
        return nil;
    }
    return [dict objectForKey:downloader.app.appName];
}

- (NSDictionary*)downloadDictionary {
    NSString* folder = [Lib getDocumentPath];
    NSString* file = [folder stringByAppendingPathComponent:@"download.plist"];
    NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithContentsOfFile:file];
    return dict;
}
@end
